﻿module		core.hgecnfont;

private import core.hgeall;
 
private import std.string;
private import std.stream;
private import std.stdio;
private import std.regexp;
private import std.windows.charset;
private import std.utf;

 

 

class hgeFontCN {
public:
    this( char[] filename)							//根据字体文件创建
    {
		if(filename in fnts){
			this= fnts[filename];
			return;
		}
		m_name= filename;
		
		// 必须先初始化 数组
		fb= new  fontBody[65536];
		
        mes("		------读取中文字体信息开始-----");
        int		tex_width;		//纹理宽度
        
        float	texx;			//纹理 X
        float	texy;			//纹理 Y


        if (!hge)hge=gameInfo.hge();

        fScale=1.0f;
        fRot=0.0f;
        fTracking=0.0f;
        hTexture=0;
        fZ=0.5f;
        nBlend=BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE;
        dwCol=0xFFFFFFFF;


        if (! std.file.exists(filename))
            throw new Exception("		载入字体文件失败!不存在此文件!	名称=	"~filename);
        if (std.file.getSize(filename) < 32 )
            throw new Exception("		载入字体文件失败!尺寸不符合!		名称=	"~filename);



//////////////////////////////开始读取 ///////////////////////////////

        mes(filename);
        File    	mfile =	new File;

        mfile.open(filename,FileMode.In);
        if (! mfile.readable)
			throw new Exception("	*打开字体文件失败	名称=	"~filename);

        mfile.position = 0;

        char[] fm= mfile.readString("[HGEFONTCN]".length);

        if (fm!="[HGEFONTCN]")
            throw new Exception("	*打开字体文件失败!不正确的字体文件头!	名称=	"~fm);


        uint imgNameSize,	fontw,	fonth;

        mfile.read(imgNameSize);								//取得字体图片文件名的长度
        char[] imgName=	mfile.readString(imgNameSize);		//取得字体图片文件名
        if (imgName == null)
            throw new Exception("	*打开字体文件失败!找不到字体纹理图片!	名称=	"~imgName);

        mfile.read(fontw);
        mfile.read(fonth);

		char[] fontPath = std.path.getDirName(filename);
		fontPath ~= r"\";
		fontPath ~= imgName;

		mes(fontPath);
		
        hTexture = gameInfo.res.tex_load(fontPath);

        // 获得纹理宽度
        tex_width=hge.Texture_GetWidth(hTexture);

        // 获得字符宽度
        char_width 	= fontw;
        fHeight 	= fonth;

        texx=texy=0.0f;

        letter = new hgeSprite(hTexture, 0, 0, fontw, fonth);



        int n= (mfile.size-mfile.position)/ st_FontCN_Body.sizeof	;	//计算从此往后还有几个字体BODY结构

        st_FontCN_Body[]	tmpFont= new st_FontCN_Body[n];
		
        mfile.readBlock(&tmpFont[0],	st_FontCN_Body.sizeof* tmpFont.length);

        wchar k;

        foreach(ti, tf;	tmpFont) {

            k=tf.hz;
            fb[k].i= tf.hz;
            fb[k].tx=tf.tx;
            fb[k].ty=tf.ty;
            if (tf.hz>= ASCII_FIX && tf.hz<= ASCII_END)	//判断字符宽度, 中文12位,英文8位
			{	
				fb[k].tw= ASCII_WIDTH;
			}else{
                fb[k].tw= fontw;
			}
        }
        wchar j;

        
        mfile.close();
		delete mfile;
		delete tmpFont;

		fnts[filename] = this;
        mes("		------读取中文字体信息完毕-----");
    }

    ~this() {
        delete letter;
		fnts.remove(m_name);
    }

	static void releaseAll(){
		foreach( f; fnts){
			delete f;
		}
	}
	static void vmes( ...) 
	{
		vmf.length=vmf.length+1;
        void putc(dchar c) {
            std.utf.encode(vmf[$-1], c);
        }
        std.format.doFormat(&putc, _arguments, _argptr);
    }
				
	void	RenderVmf(){
			uint h= gameInfo.height-60	;		// 初始位置为屏幕底边往上60 像素
			
			foreach(i,wchar[] a; vmf){
				Render(0,h-i*fHeight,HGETEXT_LEFT,a);
			}
			vmf.length=0;
		}
				
    void	Render(float x, float y, int fontAlign, wchar[] string)		//绘制字符串
    {
        float	fx=x;
        fontAlign 	&= HGETEXT_HORZMASK;
        if (fontAlign==HGETEXT_RIGHT) 	fx-=GetStringWidth(string);
        if (fontAlign==HGETEXT_CENTER) 	fx-=cast(int)(GetStringWidth(string)/2.0f);

        wchar	 tmpch;
		wchar	 tmpSpace= cast(wchar)' ';	// Unicode16 字符 空格
        foreach(j, sz;	string) {
            // 遇到回车
            if (sz=='\n') {	
                y+=fHeight*fScale;
                fx=x;
                if (fontAlign==HGETEXT_RIGHT) fx-=GetStringWidth(string);
                if (fontAlign==HGETEXT_CENTER)fx-=cast(int)(GetStringWidth(string)/2.0f);
            } 
			else if( sz== tmpSpace){
				fx+=(ASCII_WIDTH + fTracking)*fScale;		//如果是空格, 只增加距离
			}
			else if (fb[sz].i)		//存在此字
            {			//mes("a1=%s ,%d, %d, %d, %f, %f",sz,fb[sz].tx, fb[sz].ty, fb[sz].tw, fHeight, fx);
                letter.SetTextureRect(fb[sz].tx, fb[sz].ty, fb[sz].tw, fHeight);
                letter.RenderEx(fx, y, fRot, fScale);
                fx+=(fb[sz].tw + fTracking)*fScale;
            } else					// 不存在的字符
            {
                tmpch= cast(wchar)'?';
                //mes("a2=%d,   sz=%d",fb[sz].i, sz);
                if (fb[tmpch].i) {
                    letter.SetTextureRect(fb[tmpch].tx, fb[tmpch].ty, fb[sz].tw, fHeight);
                    letter.RenderEx(fx, y, fRot, fScale);
                    fx+=(fb[sz].tw +fTracking)*fScale;
                }
            }
        }

    }

    void printf(float x, float y, int fontAlign, ...) {
        wchar[] line;
        void putc(dchar c) {
            std.utf.encode(line, c);
        }
        std.format.doFormat(&putc, _arguments, _argptr);
        Render(x,y,fontAlign,line);
        delete line;		//必须使用此项,否则游戏开始2分钟后会自动退出
    }

    void		SetColor(uint col)									//设置字体颜色
    {
        dwCol=col;
        if (letter)
            letter.SetColor(col);
    }

    void		SetZ(float z)										//设置Z缓冲
    {
        fZ=z;
        if (letter)
            letter.SetZ(z);
    }


    void		SetBlendMode(int blend)							//设置混和模式
    {
        nBlend=blend;
        if (letter)
            letter.SetBlendMode(blend);

    }


    void		SetScale(float scale) 	{
        fScale=scale;
    }				//设置比例
    void		SetRotation(float rot) {
        fRot=rot;
    }					//设置旋转角度
    void		SetTracking(float tracking) {
        fTracking=tracking;
    }	//设置轨迹

    uint		GetColor()  			{
        return dwCol;
    }			//获得颜色
    float		GetZ()  				{
        return fZ;
    }				//获得Z缓冲
    int			GetBlendMode()  		{
        return nBlend;
    }			//获得混和模式
    float		GetScale()  			{
        return fScale;
    }			//过得比例
    float		GetRotation()  			{
        return fRot;
    }				//获得旋转角度
    float		GetTracking()  			{
        return fTracking;
    }		//获得轨迹
    float		GetFontHeight()  		{	//获得字体高度
        return fHeight;
    }			
	float		GetHeight()  			{	//获得字体缩放以后的高度
		return fHeight*fScale;
    }			

    float		GetStringWidth( wchar[] string)					//获得字符串的象素级宽度
    {	//获得字符串的宽度(汉字按两个字节、字母按照一个字节算)
        float w = 0;

        int i=0;
        foreach(ts;	string) {
            if (fb[ts].i)
                w += (fb[ts].tw + fTracking);
            else if (fb['?'].i)
                w += (fb['?'].tw + fTracking);
        }

		return w * fScale;
    }


    hgeSprite	GetSprite()						//获得指定的精灵
    {
        return letter;
    }

	this(hgeFontCN fn){
		letter=	fn.letter;
		fb=	fn.fb.dup;
		hTexture= fn.hTexture;
		fHeight=	fn.fHeight;
		fScale=		fn.fScale;
		fRot=		fn.fRot;
		fTracking=	fn.fTracking;
		dwCol=		fn.dwCol;
		fZ=			fn.fZ;
		nBlend=		fn.nBlend;
	}
		
private:
    this() {		};
    								//根据字体对象创建
    static ifHge	hge;

    hgeSprite		letter;

    struct		fontBody {
        ushort	i;		//是否存在此字
        ushort	tx;
        ushort ty;
        ushort tw;		//宽
    }

    fontBody[]	fb;
    HTEXTURE	hTexture;
    float		fHeight;
    float		fScale, fRot;
    float		fTracking;

	struct		VmesInfo{
		float	 	x;
		float 		y;
		int   		_align;
		wchar[]	info;
	}

	static wchar[][]		vmf;	// 供其它模块使用的输出暂存器, 最后将此变量一次性输出到屏幕
		
    uint		dwCol;
    float		fZ;
    int			nBlend;

	char[]		m_name;					//字体文件名 
static	hgeFontCN[char[]] 		fnts;	//字体数组 
};

